import "reflect-metadata";
interface ModuleMetadata {
  controllers?: Function[];
  providers?: any;
  exports?: any; //模块的导出  可以把自己的一部分providers导出给别的模块 别的模块只要导入了自己这个模块
  imports?: any; //模块的导入  可以导入别的模块 把别的模块的导出的providers导入到自己的providers中
}
//定义模块装饰器
export function Module(metadata: ModuleMetadata): ClassDecorator {
  return (target: any) => {
    //当一个类使用Module装饰器的时候 就可以添加标识 它是一个模块的元数据
    Reflect.defineMetadata("isModule", true, target);
    //给模块类添加元数据 元数据的名字叫controllers 值是controllers 数组 [AppController]
    //给模块类AppModule添加元数据 providers 值是[LoggerService]
    defineModule(target, metadata.controllers);
    Reflect.defineMetadata("controllers", metadata.controllers, target);
    //在类上保存了一个providers的数组 表示给此模块注入的providers的供应者
    // let providers = (metadata.providers ?? [])
    //   .map((provider) => {
    //     if (provider instanceof Function) {
    //       return provider;
    //     } else if (provider?.useClass instanceof Function) {
    //       return provider.useClass;
    //     } else {
    //       return null;
    //     }
    //   })
    //   .filter(Boolean);
    defineModule(
      target,
      (metadata.providers ?? [])
        .map((provider) =>
          provider instanceof Function ? provider : provider.useClass
        )
        .filter(Boolean)
    );
    Reflect.defineMetadata("providers", metadata.providers, target);
    Reflect.defineMetadata("exports", metadata.exports, target);
    Reflect.defineMetadata("imports", metadata.imports, target);
  };
}

export function defineModule(module, targets = []) {
  //遍历targets数组 为每个元数添加元数据 key是nestModule 值是对应的模块
  targets.forEach((target) => {
    Reflect.defineMetadata("nestModule", module, target);
  });
}

export function Global() {
  return (target: Function) => {
    Reflect.defineMetadata("global", true, target);
  };
}

export interface DynamicModule extends ModuleMetadata {
  module: Function;
}
